<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>哈利波特体验</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
    <style>
        body {
            margin: 40px;
            background: #f7f8fa;
            font-family: "Microsoft YaHei", Arial, sans-serif;
        }

        .main-container {
            display: flex;
            height: 100%;
            align-items: stretch;
            justify-content: center;
            gap: 10px;
        }

        .left-panel {
            width: 360px;
            height: 676px;
            background: #fff;
            border-radius: 24px;
            margin: 32px 32px 32px 32px;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
        }

        .avatar-box {
            width: 100%;
            height: 100%;
            background: linear-gradient(180deg, #ffffff 0%, #fff 100%);
            border-radius: 32px;
            display: flex;
            align-items: center;
            justify-content: center;
            box-shadow: 0 8px 32px 0 rgb(255, 255, 255);
            position: relative;
        }

        .avatar-img {
            width: 100%;
            height: 100%;
            object-fit: cover;
            border-radius: 28px;
            box-shadow: 0 0 48px 24px rgba(255, 255, 255, 0.18);
            background: radial-gradient(circle, rgba(252, 252, 252, 0.7) 0%, rgba(255, 255, 255, 0.2) 80%, transparent 100%);
        }

        .call-btn {
            margin-top: 12px;
            padding: 12px 32px;
            background: #6c63ff;
            color: #fff;
            border: none;
            border-radius: 24px;
            font-size: 18px;
            cursor: pointer;
            box-shadow: 0 2px 8px rgba(108, 99, 255, 0.12);
            transition: background 0.2s;
        }

        .call-btn:hover {
            background: #554eea;
        }

        .right-panel {
            flex: 1;
            margin: 32px 32px 32px 0;
            display: flex;
            flex-direction: column;
            justify-content: flex-start;
        }

        .chat-card {
            background: #fff;
            border-radius: 24px;
            box-shadow: 0 2px 16px rgba(0, 0, 0, 0.06);
            padding: 32px;
            min-height: 150px;
            margin-bottom: 10px;
            display: flex;
            flex-direction: column;
        }

        #chatBubbleList {
            height: 430px;
            overflow-y: auto;
            display: flex;
            flex-direction: column;
        }

        .chat-message {
            font-size: 18px;
            margin-bottom: 12px;
            max-width: 70%;
            padding: 12px 20px;
            border-radius: 18px;
            word-break: break-word;
            display: block;
            width: fit-content;
        }

        .chat-message.ai {
            background: #f0f0f0;
            color: #222;
            margin-left: 0;
            margin-right: auto;
        }

        .chat-message.user {
            background: #6c63ff;
            color: #fff;
            margin-left: auto;
            margin-right: 0;
        }

        .input-area {
            display: flex;
            align-items: center;
            background: #fff;
            border-radius: 16px;
            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
            padding: 16px 24px;
        }

        .input-area input {
            flex: 1;
            font-size: 16px;
            border: none;
            outline: none;
            background: transparent;
            margin-right: 12px;
        }

        .send-btn {
            background: #6c63ff;
            color: #fff;
            border: none;
            border-radius: 16px;
            padding: 8px 20px;
            font-size: 16px;
            cursor: pointer;
            transition: background 0.2s;
        }

        .send-btn:hover {
            background: #554eea;
        }

        .footer {
            text-align: center;
            color: #999;
            font-size: 13px;
            margin: 10px;
        }

        /* 添加控制按钮样式 */
        .control-buttons {
            display: flex;
            gap: 12px;
            margin-bottom: 16px;
        }

        .control-btn {
            flex: 1;
            padding: 10px 16px;
            border: 1px solid #ddd;
            border-radius: 12px;
            background: #fff;
            cursor: pointer;
            font-size: 16px;
            transition: all 0.2s;
        }

        .control-btn:hover {
            background: #f0f0f0;
        }

        .control-btn.active {
            background: #6c63ff;
            color: white;
            border-color: #6c63ff;
        }

        /* 状态显示样式 */
        .status {
            padding: 8px 12px;
            border-radius: 8px;
            margin-top: 8px;
            font-size: 14px;
        }

        .status-success {
            background-color: #d4edda;
            color: #155724;
            border: 1px solid #c3e6cb;
        }

        .status-error {
            background-color: #f8d7da;
            color: #721c24;
            border: 1px solid #f5c6cb;
        }

        .status-info {
            background-color: #d1ecf1;
            color: #0c5460;
            border: 1px solid #bee5eb;
        }

        /* 音频控制按钮样式 */
        .audio-controls {
            display: flex;
            gap: 12px;
            margin-top: 16px;
        }

        .audio-btn {
            display: flex;
            align-items: center;
            justify-content: center;
            width: 48px;
            height: 48px;
            border: none;
            border-radius: 50%;
            background: #6c63ff;
            color: white;
            font-size: 20px;
            cursor: pointer;
            transition: all 0.2s;
        }

        .audio-btn:hover {
            background: #554eea;
            transform: scale(1.05);
        }

        .audio-btn:disabled {
            background: #ccc;
            cursor: not-allowed;
            transform: none;
        }

        .live-indicator {
            display: inline-block;
            width: 8px;
            height: 8px;
            background-color: #ff4d4f;
            border-radius: 50%;
            margin-right: 6px;
            animation: pulse 1.5s infinite;
        }

        @keyframes pulse {
            0% {
                opacity: 1;
            }
            50% {
                opacity: 0.5;
            }
            100% {
                opacity: 1;
            }
        }
    </style>
</head>
<body>
<div style="width:97%;display:flex;align-items:center;gap: 20px;margin-top:-15px;background:#f7f8fa;margin-bottom:0;">
    <a href="index.html"
       style="display:inline-block;font-size:16px;color:#564fb3;background:#e0dfee;border:none;border-radius:16px;padding:8px 24px;margin-left:32px;text-decoration:none;box-shadow:0 2px 8px rgba(108,99,255,0.10);transition:background 0.2s;cursor:pointer;">←
        返回首页</a>
    <div style="flex:1;height:2px;background:#e5e5e5;"></div>
</div>
<div class="main-container">
    <!-- 左侧会话列表面板 -->
    <div class="session-panel"
         style="width: 280px; background: #fff; border-radius: 24px; margin: 32px 0 32px 32px; display: flex; flex-direction: column;">
        <div class="session-header"
             style="padding: 20px; border-bottom: 1px solid #f0f0f0; display: flex; justify-content: space-between; align-items: center;">
            <h3 style="margin: 0; font-size: 18px;">对话历史</h3>
            <button id="newSessionBtn" class="new-session-btn"
                    style="padding: 6px 16px; background: #6c63ff; color: white; border: none; border-radius: 12px; cursor: pointer;">
                新建会话
            </button>
        </div>
        <div id="sessionList" class="session-list" style="flex: 1; overflow-y: auto; padding: 8px;">
            <!-- 会话列表将通过JavaScript动态生成 -->
        </div>
    </div>

    <div class="left-panel">
        <div class="avatar-box">
            <button class="call-btn" onclick="startVoiceChat()"
                    style="position:absolute;top:560px;left:50%;transform:translateX(-50%);z-index:2;box-shadow:0 4px 16px rgba(108,99,255,0.18);">
                语音通话
            </button>
            <video class="avatar-img" autoplay loop muted playsinline>
                <source src="../src/main/resources/imgs/halibote2.mp4" type="video/mp4">
                您的浏览器不支持视频标签。
            </video>
        </div>
    </div>
    <div class="right-panel">
        <div class="chat-card" id="chatCard">
            <div id="chatBubbleList">
                <div class="chat-message ai">嗨，我是哈利……哈利·波特。</div>
            </div>
            <div style="margin:16px 0 0 0;">
                <audio id="chatAudioPlayer" controls style="width:100%;margin-top:8px;"></audio>
                <div id="chatStatus" class="status"
                     style="color:#6c63ff;margin-top:8px;margin-bottom: -10px;margin-left: 5px;"></div>
            </div>
        </div>
        <div class="input-area" style="margin-bottom:0;">
            <!-- 添加模式切换按钮 - 微信风格 -->
            <button id="modeToggleBtn" class="mode-toggle-btn"
                    style="width:40px;height:40px;border-radius:50%;background-color:#f0f0f0;border:none;display:flex;align-items:center;justify-content:center;margin-right:8px;cursor:pointer;">
                <i style="font-size:18px;">🎤</i>
            </button>

            <!-- 文字输入区域 -->
            <div id="textInputArea" style="display:flex;flex:1;">
                <textarea class="form-control" id="chatText" placeholder="请输入您想对AI说的话..."
                          style="flex:1;height:32px;resize:vertical;border-radius:18px;padding:10px 14px;border:1px solid #e5e5e5;font-size:16px;outline:none;margin-right:8px;"></textarea>
                <button id="chatBtn" class="send-btn" style="padding:8px 20px;">发送消息</button>
            </div>

            <!-- 语音输入区域 - 默认隐藏 -->
            <div id="voiceInputArea" style="display:none;flex:1;justify-content:center;align-items:center;">
                <button id="voiceRecordBtn" class="voice-record-btn"
                        style="width:200px;height:50px;border-radius:25px;background-color:#2196F3;border:none;color:white;font-size:16px;cursor:pointer;display:flex;align-items:center;justify-content:center;">
                    按住 说话
                </button>
            </div>
        </div>
        <div class="footer">
            所有内容均由人工智能模型生成。我们对其生成内容的准确性、完整性和功能性不做任何保证，且生成的内容不代表我们的态度或观点。
        </div>
    </div>
</div>
<script>
    // 全局变量
    let ws = null; // WebSocket连接
    let mediaRecorder = null; // 媒体录音器
    let audioContext = null; // 音频上下文
    let mediaStream = null; // 媒体流
    let audioProcessor = null; // 音频处理器
    let isRecording = false; // 是否正在录音
    let chatMode = 'text'; // 对话模式：voice/text
    let aiResponseElement = null; // AI回复元素
    let isProcessing = false; // 是否正在处理
    let mediaSource = null; // 媒体源 - 新增
    let sourceBuffer = null; // 源缓冲区 - 新增
    let audioQueue = []; // 音频队列
    let isPlaying = false; // 是否正在播放音频
    let userId = 1; // 用户ID
    let sessionId = 'session_' + Date.now(); // 会话ID
    let currentSession = null; // 当前会话
    let pcmData = []; // 存储PCM数据
    let savedFilePath = ''; // 存储保存的文件路径
    let audioUrl = null; // 音频URL - 新增

    // DOM元素
    const chatText = document.getElementById('chatText');
    const chatBtn = document.getElementById('chatBtn');
    const chatStatus = document.getElementById('chatStatus');
    const chatAudioPlayer = document.getElementById('chatAudioPlayer');
    const chatBubbleList = document.getElementById('chatBubbleList');
    const startRecordingBtn = document.getElementById('startRecordingBtn');
    const stopRecordingBtn = document.getElementById('stopRecordingBtn');
    const cancelRecordingBtn = document.getElementById('cancelRecordingBtn');

    // 添加新模式切换相关元素
    const modeToggleBtn = document.getElementById('modeToggleBtn');
    const textInputArea = document.getElementById('textInputArea');
    const voiceInputArea = document.getElementById('voiceInputArea');
    const voiceRecordBtn = document.getElementById('voiceRecordBtn');

    // 初始化页面
    function initPage() {
        // 设置模式切换按钮事件
        if (modeToggleBtn) {
            modeToggleBtn.addEventListener('click', toggleChatMode);
        }

        // 设置语音录制按钮事件
        if (voiceRecordBtn) {
            // 鼠标按下开始录音
            voiceRecordBtn.addEventListener('mousedown', startVoiceRecording);
            // 鼠标松开停止录音
            document.addEventListener('mouseup', stopVoiceRecording);
            // 鼠标移出按钮停止录音
            voiceRecordBtn.addEventListener('mouseleave', stopVoiceRecording);

            // 触摸设备支持
            voiceRecordBtn.addEventListener('touchstart', (e) => {
                e.preventDefault();
                startVoiceRecording();
            });
            voiceRecordBtn.addEventListener('touchend', (e) => {
                e.preventDefault();
                stopVoiceRecording();
            });
        }

        // 加载会话列表
        loadSessionList();

        // 添加新建会话按钮事件
        if (document.getElementById('newSessionBtn')) {
            document.getElementById('newSessionBtn').addEventListener('click', createNewSession);
        }

        // 文字消息发送事件
        chatBtn.addEventListener('click', async () => {
            const text = chatText.value.trim();
            if (!text) {
                showStatus(chatStatus, '错误', '请输入对话内容', 'error');
                return;
            }

            if (isProcessing) {
                showStatus(chatStatus, '提示', '正在处理上一条消息，请稍候...', 'info');
                return;
            }

            chatBtn.disabled = true;
            chatText.disabled = true;
            isProcessing = true;

            // 插入用户气泡
            const userBubble = document.createElement('div');
            userBubble.className = 'chat-message user';
            userBubble.textContent = text;
            chatBubbleList.appendChild(userBubble);
            chatBubbleList.scrollTop = chatBubbleList.scrollHeight;

            // 清空输入框
            chatText.value = '';

            showStatus(chatStatus, '思考中', 'AI正在思考...', 'info');

            try {
                // 初始化WebSocket连接
                initWebSocket();

                // 使用当前会话ID
                if (currentSession) {
                    sessionId = currentSession.sessionId;
                }

                // 等待WebSocket连接建立
                const maxWaitTime = 3000;
                const startTime = Date.now();
                while (!ws || ws.readyState !== WebSocket.OPEN) {
                    if (Date.now() - startTime > maxWaitTime) {
                        throw new Error('WebSocket连接超时');
                    }
                    await new Promise(resolve => setTimeout(resolve, 100));
                }

                // 发送文本消息
                ws.send(JSON.stringify({
                    type: 'text_message',
                    text: text,
                    userId: userId,
                    sessionId: sessionId,
                    character: 'harry_potter'
                }));

            } catch (error) {
                console.error('发送消息失败:', error);
                showStatus(chatStatus, '错误', '发送消息失败：' + error.message, 'error');
                resetProcessingState();
                chatBtn.disabled = false;
                chatText.disabled = false;
            }
        });
    }

    // 切换对话模式
    function toggleChatMode() {
        if (isProcessing) {
            showStatus(chatStatus, '提示', '正在处理上一条消息，请稍候...', 'info');
            return;
        }

        // 切换模式
        chatMode = (chatMode === 'text') ? 'voice' : 'text';
        updateUIForMode(chatMode);
    }

    // 根据模式更新UI
    function updateUIForMode(mode) {
        if (mode === 'voice') {
            // 语音模式
            modeToggleBtn.innerHTML = '<i style="font-size:18px;">📝</i>'; // 显示文字图标
            textInputArea.style.display = 'none';
            voiceInputArea.style.display = 'flex';
        } else {
            // 文字模式
            modeToggleBtn.innerHTML = '<i style="font-size:18px;">🎤</i>'; // 显示麦克风图标
            textInputArea.style.display = 'flex';
            voiceInputArea.style.display = 'none';
        }
    }

    // 开始语音录制
    function startVoiceRecording() {
        if (isProcessing || isRecording) return;

        isRecording = true;
        voiceRecordBtn.textContent = '松开发送';
        voiceRecordBtn.style.backgroundColor = '#ff4d4f';

        showStatus(chatStatus, '录音中', '正在录音...', 'info');

        // 调用原有的录音逻辑
        startRecording();
    }

    // 停止语音录制
    function stopVoiceRecording() {
        if (!isRecording) return;

        // 先调用停止录音逻辑，再更新状态
        stopRecording();

        isRecording = false;
        voiceRecordBtn.textContent = '按住 说话';
        voiceRecordBtn.style.backgroundColor = '#2196F3';
    }

    // 停止录音
    function stopRecording() {
        // 先保存音频文件到服务器，而不是直接发送base64数据
        if (pcmData.length > 0) {
            saveAudioToServer();
        }

        // 停止音频处理
        if (audioProcessor) {
            audioProcessor.onaudioprocess = null;
            audioProcessor.disconnect();
            audioProcessor = null;
        }

        // 停止媒体流
        if (mediaStream) {
            mediaStream.getTracks().forEach(track => track.stop());
            mediaStream = null;
        }

        // 创建语音消息气泡 - 类似微信的效果
        const voiceBubble = document.createElement('div');
        voiceBubble.className = 'chat-message user';
        voiceBubble.innerHTML = '<i>🎤</i> [语音消息]';
        chatBubbleList.appendChild(voiceBubble);
        chatBubbleList.scrollTop = chatBubbleList.scrollHeight;

        resetRecordingState();
    }

    // 取消录音
    function cancelRecording() {
        // 停止音频处理
        if (audioProcessor) {
            audioProcessor.disconnect();
            audioProcessor = null;
        }

        // 停止媒体流
        if (mediaStream) {
            mediaStream.getTracks().forEach(track => track.stop());
            mediaStream = null;
        }

        // 关闭WebSocket连接
        if (ws) {
            ws.close();
            ws = null;
        }

        resetRecordingState();
        showStatus(chatStatus, '已取消', '录音已取消', 'info');
    }

    // 重置录音状态
    function resetRecordingState() {
        startRecordingBtn.disabled = false;
        stopRecordingBtn.disabled = true;
        cancelRecordingBtn.disabled = true;
        isRecording = false;
    }

    // 初始化WebSocket连接
    function initWebSocket() {
        if (!('WebSocket' in window)) {
            showStatus(chatStatus, '错误', '浏览器不支持WebSocket功能', 'error');
            return;
        }

        // 确保使用正确的端口
        const wsUrl = `ws://localhost:8080/ws/chat`;

        // 关闭已有的连接
        if (ws) {
            ws.close();
        }

        ws = new WebSocket(wsUrl);

        ws.onopen = () => {
            console.log('WebSocket连接已建立');
            showStatus(chatStatus, '连接成功', 'WebSocket连接已建立', 'info');
            // 发送配置信息
            ws.send(JSON.stringify({
                type: 'config',
                config: {
                    userId: userId,
                    sessionId: sessionId,
                    character: 'harry_potter', // 哈利波特角色标识
                    format: 'pcm',
                    sampleRate: 16000,
                    bits: 16,
                    channel: 1,
                    enablePunc: true
                }
            }));
        };

        ws.onmessage = (event) => {
            try {
                const data = JSON.parse(event.data);
                console.log('收到WebSocket消息:', data);

                // 处理不同类型的消息
                switch (data.type) {
                    case 'connected':
                        // 连接成功
                        showStatus(chatStatus, '连接成功', 'WebSocket连接已建立', 'info');
                        break;
                    case 'status':
                        // 状态更新
                        showStatus(chatStatus, '处理中', data.message, 'info');
                        break;
                    case 'stream_text':
                        // 流式文本回复
                        appendTextToResponse(data.text);
                        break;
                    case 'complete':
                        // 处理完成
                        handleCompleteMessage(data);
                        break;
                    case 'error':
                        // 错误处理
                        handleErrorMessage(data);
                        break;
                    case 'asr_result':
                        // 语音识别结果
                        showStatus(chatStatus, '识别完成', '语音识别结果: ' + data.text, 'info');
                        break;
                    case 'audio_segment':
                        // 音频片段处理 - 确保正确接收和处理audioData和sequence
                        handleAudioSegment(data.audioData || data.data, data.sequence || 0);
                        break;
                    case 'config_ack':
                        // 配置确认
                        console.log('配置已确认:', data.message);
                        break;
                }
            } catch (error) {
                console.error('解析WebSocket消息失败:', error);
            }
        };

        ws.onclose = (event) => {
            console.log('WebSocket连接已关闭:', event.code, event.reason);
            // 只有在非正常关闭时才显示错误信息
            if (event.code !== 1000) {
                showStatus(chatStatus, '连接关闭', 'WebSocket连接已关闭', 'info');
            }
        };

        ws.onerror = (error) => {
            console.error('WebSocket错误:', error);
            showStatus(chatStatus, '错误', 'WebSocket连接错误', 'error');
        };
    }

    // 处理完整消息 - 修复参数不匹配问题，确保状态正确重置
    function handleCompleteMessage(data) {
        // 无论如何都先设置isProcessing为false，确保输入框可以被点击
        isProcessing = false;
        chatBtn.disabled = false;
        chatText.disabled = false;

        console.log('接收到完成消息:', data);
        showStatus(chatStatus, '完成', 'AI回复已完成', 'success');

        // 延迟清理资源，确保音频有足够时间播放
        // 只有在音频没有播放或播放已结束时才立即清理
        if (!isPlaying && audioQueue.length === 0) {
            // 添加短暂延迟确保音频UI更新
            setTimeout(() => {
                resetProcessingState();
                aiResponseElement = null;
            }, 1000);
        } else {
            // 音频还在播放或队列中还有音频，稍后再清理
            aiResponseElement = null;
            // 注意：不再立即重置处理状态，让音频继续播放
        }

        // 重新加载会话列表，确保最新对话显示
        setTimeout(() => {
            loadSessionList();
        }, 1500);
    }

    // 处理错误消息
    function handleErrorMessage(data) {
        console.error('处理错误:', data.message);
        showStatus(chatStatus, '错误', data.message || '处理失败', 'error');
        isProcessing = false;
        chatBtn.disabled = false;
        chatText.disabled = false;
        resetProcessingState();
    }

    // 重置处理状态
    function resetProcessingState() {
        isProcessing = false;
        chatBtn.disabled = false;
        chatText.disabled = false;
        // 确保音频相关状态也被正确重置
        isPlaying = false;
        audioQueue = [];

        if (audioContext) {
            audioContext.close().then(() => {
                audioContext = null;
            });
        }
        if (mediaStream) {
            mediaStream.getTracks().forEach(track => track.stop());
            mediaStream = null;
        }
        if (audioProcessor) {
            audioProcessor.disconnect();
            audioProcessor = null;
        }
    }

    // 添加文本到回复区域
    function appendTextToResponse(text) {
        if (!aiResponseElement) {
            // 创建新的AI回复元素
            aiResponseElement = document.createElement('div');
            aiResponseElement.className = 'chat-message ai';
            chatBubbleList.appendChild(aiResponseElement);
        }

        // 处理加粗标记
        let processedText = text;
        // 将**文本**替换为<strong>文本</strong>
        processedText = processedText.replace(/\*\*([^*]+?)\*\*/g, '<strong>$1</strong>');

        // 修改为追加操作符
        aiResponseElement.innerHTML += processedText;

        // 滚动到底部
        chatBubbleList.scrollTop = chatBubbleList.scrollHeight;
    }

    // 处理音频片段 - 增强状态管理和日志
    function handleAudioSegment(audioBase64, sequence) {
        try {
            // 检查音频数据是否有效
            if (!audioBase64 || typeof audioBase64 !== 'string' || audioBase64.trim() === '') {
                console.warn('接收到无效的音频数据，跳过处理');
                return;
            }

            // 如果是第一个音频片段，初始化MediaSource
            if (!mediaSource) {
                initMediaSource();
            }

            // 将base64转换为ArrayBuffer
            const binaryString = atob(audioBase64);
            const len = binaryString.length;
            const bytes = new Uint8Array(len);
            for (let i = 0; i < len; i++) {
                bytes[i] = binaryString.charCodeAt(i);
            }

            // 添加到音频队列
            audioQueue.push(bytes.buffer);
            console.log('音频队列大小:', audioQueue.length, '当前序列:', sequence);

            // 如果sourceBuffer已准备好且不在更新状态，立即处理队列
            if (sourceBuffer && !sourceBuffer.updating && audioQueue.length > 0) {
                const firstAudioChunk = audioQueue.shift();
                appendToSourceBuffer(firstAudioChunk);
            }

            // 检查是否为最后一个音频片段
            if (sequence < 0) {
                console.log('收到最后一个音频片段');
                // 标记为正在播放
                isPlaying = true;

                // 当队列处理完毕后结束流
                if (audioQueue.length === 0 && sourceBuffer && !sourceBuffer.updating) {
                    mediaSource.endOfStream();
                }
            }
        } catch (error) {
            console.error('处理音频片段失败:', error);
            // 出错时尝试降级处理
            fallbackToCompleteAudio();
        }
    }

    // 初始化MediaSource - 增强错误处理和用户交互提示
    function initMediaSource() {
        try {
            mediaSource = new MediaSource();

            // 当MediaSource准备就绪时
            mediaSource.addEventListener('sourceopen', () => {
                try {
                    // 为mp3格式创建sourceBuffer
                    const mimeType = 'audio/mpeg';
                    if (MediaSource.isTypeSupported(mimeType)) {
                        sourceBuffer = mediaSource.addSourceBuffer(mimeType);

                        // 监听updateend事件，处理队列中的音频片段
                        sourceBuffer.addEventListener('updateend', () => {
                            if (audioQueue.length > 0 && !sourceBuffer.updating) {
                                const nextAudioChunk = audioQueue.shift();
                                appendToSourceBuffer(nextAudioChunk);
                            }
                        });

                        // 如果队列中已有音频片段，立即处理
                        if (audioQueue.length > 0) {
                            const firstAudioChunk = audioQueue.shift();
                            appendToSourceBuffer(firstAudioChunk);
                        }
                    } else {
                        console.error('浏览器不支持音频格式: ' + mimeType);
                        // 降级处理：使用传统方式播放完整音频
                        fallbackToCompleteAudio();
                    }
                } catch (error) {
                    console.error('初始化sourceBuffer失败:', error);
                    fallbackToCompleteAudio();
                }
            });

            // 设置音频源
            audioUrl = URL.createObjectURL(mediaSource);
            chatAudioPlayer.src = audioUrl;

            // 尝试自动播放，但添加更友好的用户交互提示
            chatAudioPlayer.play().catch(e => {
                console.log('自动播放被阻止，等待用户交互后播放:', e);
                showStatus(chatStatus, '提示', '请点击播放器播放AI回复', 'info');
            });
        } catch (error) {
            console.error('初始化MediaSource失败:', error);
            fallbackToCompleteAudio();
        }
    }

    // 添加音频数据到sourceBuffer - 确保播放状态
    function appendToSourceBuffer(audioData) {
        try {
            if (sourceBuffer && mediaSource && mediaSource.readyState === 'open') {
                sourceBuffer.appendBuffer(audioData);
                // 确保音频在添加数据后处于播放状态
                if (chatAudioPlayer.paused) {
                    chatAudioPlayer.play().catch(e => {
                        console.log('自动播放被阻止，等待用户交互后播放:', e);
                    });
                }
            }
        } catch (error) {
            console.error('追加音频数据失败:', error);
            fallbackToCompleteAudio();
        }
    }

    // 降级处理：使用传统方式播放完整音频 - 新增函数
    function fallbackToCompleteAudio() {
        console.log('使用降级方案播放音频');
        // 收集所有音频数据
        let completeAudioData = new Blob(audioQueue, {type: 'audio/mpeg'});
        let audioUrl = URL.createObjectURL(completeAudioData);
        chatAudioPlayer.src = audioUrl;
        chatAudioPlayer.play().then(() => {
            console.log('降级模式下音频播放成功');
        }).catch(e => {
            console.error('降级模式下播放失败:', e);
            showStatus(chatStatus, '提示', '请点击播放按钮收听AI回复', 'info');
        });
    }

    // 保留完整的资源清理版本
    function resetProcessingState() {
        // 清理之前的音频资源
        if (audioUrl) {
            URL.revokeObjectURL(audioUrl);
            audioUrl = null;
        }

        // 重置变量
        mediaSource = null;
        sourceBuffer = null;
        audioQueue = [];
        isPlaying = false;
        isProcessing = false;
        chatBtn.disabled = false;
        chatText.disabled = false;
        chatAudioPlayer.src = '';

        // 确保音频相关状态也被正确重置
        if (audioContext) {
            audioContext.close().then(() => {
                audioContext = null;
            });
        }
        if (mediaStream) {
            mediaStream.getTracks().forEach(track => track.stop());
            mediaStream = null;
        }
        if (audioProcessor) {
            audioProcessor.disconnect();
            audioProcessor = null;
        }
    }

    // 播放下一个音频片段 - 保留旧实现作为备用
    function playNextAudioSegment() {
        if (audioQueue.length === 0) {
            isPlaying = false;
            console.log('音频队列为空，停止播放');
            return;
        }

        isPlaying = true;
        const audioData = audioQueue.shift();

        // 创建音频Blob
        const audioBlob = new Blob([audioData], {type: 'audio/mpeg'});
        const audioUrl = URL.createObjectURL(audioBlob);

        console.log('开始播放音频片段');

        // 设置音频播放器
        chatAudioPlayer.src = audioUrl;
        chatAudioPlayer.play().then(() => {
            console.log('音频播放成功');
        }).catch(e => {
            console.error('自动播放失败:', e);
            isPlaying = false;
            // 尝试使用用户交互触发播放 - 添加提示给用户
            showStatus(chatStatus, '提示', '请点击播放按钮收听AI回复', 'info');
        });

        // 监听播放结束事件
        chatAudioPlayer.onended = function () {
            URL.revokeObjectURL(audioUrl);
            playNextAudioSegment();
        };
    }

    // 工具函数
    function showStatus(element, title, message, type) {
        let bgClass = '';
        let icon = '';

        switch (type) {
            case 'success':
                bgClass = 'status-success';
                icon = '✓';
                break;
            case 'error':
                bgClass = 'status-error';
                icon = '✗';
                break;
            case 'info':
                bgClass = 'status-info';
                icon = 'i';
                break;
        }

        element.className = 'status ' + bgClass;
        element.innerHTML = `<strong>${icon} ${title}:</strong> ${message}`;
    }

    function floatTo16BitPCM(float32Array) {
        const buffer = new ArrayBuffer(float32Array.length * 2);
        const view = new DataView(buffer);

        for (let i = 0; i < float32Array.length; i++) {
            const s = Math.max(-1, Math.min(1, float32Array[i]));
            view.setInt16(i * 2, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
        }

        return buffer;
    }

    function arrayBufferToBase64(buffer) {
        let binary = '';
        const bytes = new Uint8Array(buffer);
        const len = bytes.byteLength;

        for (let i = 0; i < len; i++) {
            binary += String.fromCharCode(bytes[i]);
        }

        return btoa(binary);
    }

    // 开始录音 - 完善实现
    function startRecording() {
        try {
            // 检查浏览器支持
            if (!('getUserMedia' in navigator.mediaDevices)) {
                showStatus(chatStatus, '错误', '浏览器不支持麦克风采集功能', 'error');
                return;
            }

            // 获取用户媒体设备（麦克风）
            navigator.mediaDevices.getUserMedia({
                audio: {
                    echoCancellation: true,
                    noiseSuppression: true,
                    sampleRate: 16000
                }
            }).then(stream => {
                mediaStream = stream;

                // 创建音频上下文
                audioContext = new (window.AudioContext || window.webkitAudioContext)({
                    sampleRate: 16000  // 设置采样率为16kHz
                });

                // 创建麦克风输入节点
                const microphone = audioContext.createMediaStreamSource(mediaStream);

                // 创建音频处理器节点
                audioProcessor = audioContext.createScriptProcessor(4096, 1, 1);

                // 清空之前的PCM数据
                pcmData = [];

                // 音频处理回调函数
                audioProcessor.onaudioprocess = function (event) {
                    // 获取输入音频数据（单声道）
                    const inputData = event.inputBuffer.getChannelData(0);

                    // 将Float32数据转换为16位PCM整数
                    const int16Data = new Int16Array(inputData.length);
                    for (let i = 0; i < inputData.length; i++) {
                        // 音频数据归一化并转换为16位整数
                        const s = Math.max(-1, Math.min(1, inputData[i]));
                        int16Data[i] = s < 0 ? s * 0x8000 : s * 0x7FFF;
                    }

                    // 存储PCM数据
                    pcmData.push(...int16Data);
                };

                // 连接音频节点
                microphone.connect(audioProcessor);
                audioProcessor.connect(audioContext.destination);

                // 初始化WebSocket连接（如果尚未连接）
                if (!ws || ws.readyState !== WebSocket.OPEN) {
                    initWebSocket();
                }

            }).catch(error => {
                console.error('启动录音失败:', error);
                showStatus(chatStatus, '错误', '无法启动录音：' + error.message, 'error');
                resetRecordingState();
            });

        } catch (error) {
            console.error('启动录音失败:', error);
            showStatus(chatStatus, '错误', '无法启动录音：' + error.message, 'error');
            resetRecordingState();
        }
    }


    // 保存音频文件到服务器
    async function saveAudioToServer() {
        try {
            // 生成唯一文件名
            const timestamp = Date.now();
            const fileName = `voice_chat_${timestamp}.pcm`;

            // 将Int16Array转换为Blob
            const blob = new Blob([new Int16Array(pcmData)], {type: 'application/octet-stream'});

            const formData = new FormData();
            formData.append('audioFile', blob, fileName);

            showStatus(chatStatus, '处理中', '正在上传录音文件...', 'info');
            isProcessing = true;

            // 调用保存文件接口
            const response = await axios.post('http://localhost:8080/user/ai/save-audio', formData, {
                timeout: 10000,
                headers: {
                    'Content-Type': 'multipart/form-data'
                }
            });

            if (response.data.code === 1 && response.data.data) {
                savedFilePath = response.data.data;
                console.log('文件保存成功，路径:', savedFilePath);

                // 初始化WebSocket连接并发送语音聊天请求
                initWebSocket();

                // 等待WebSocket连接建立后发送语音聊天请求
                setTimeout(() => {
                    if (ws && ws.readyState === WebSocket.OPEN) {
                        ws.send(JSON.stringify({
                            type: 'voice_chat',
                            filePath: savedFilePath,
                            sessionId: sessionId,
                            userId: userId
                        }));
                        showStatus(chatStatus, '处理中', '正在识别并生成回复...', 'info');
                    } else {
                        showStatus(chatStatus, '错误', 'WebSocket连接失败，无法处理语音消息', 'error');
                        resetProcessingState();
                    }
                }, 500);
            } else {
                console.error('文件保存失败:', response.data);
                showStatus(chatStatus, '错误', '文件保存失败: ' + (response.data.message || '未知错误'), 'error');
                resetProcessingState();
            }
        } catch (error) {
            console.error('保存音频文件失败:', error);
            showStatus(chatStatus, '错误', '保存录音文件失败: ' + error.message, 'error');
            resetProcessingState();
        }
    }

    // 初始化页面
    window.addEventListener('DOMContentLoaded', function () {
        initPage();
        // 初始化全局变量
        pcmData = [];

        // 加载会话列表后检查是否有现有会话，如果没有则自动创建
        setTimeout(() => {
            const sessionListElement = document.getElementById('sessionList');
            if (sessionListElement && sessionListElement.innerHTML.includes('暂无对话历史')) {
                console.log('没有现有会话，自动创建新会话');
                createNewSession();
            }
        }, 1000);
    });

    // 加载会话列表
    function loadSessionList() {
        const sessionListElement = document.getElementById('sessionList');
        if (!sessionListElement) return;

        sessionListElement.innerHTML = '<div style="text-align: center; padding: 20px; color: #999;">加载中...</div>';

        // 修复：使用完整的URL
        axios.get('http://localhost:8080/user/ai-session/list', {
            params: {userId: userId}
        })
            .then(response => {
                const sessions = response.data.data;
                sessionListElement.innerHTML = '';

                if (sessions.length === 0) {
                    sessionListElement.innerHTML = '<div style="text-align: center; padding: 40px 20px; color: #999;">暂无对话历史<br>点击"新建会话"开始对话</div>';
                    return;
                }

                // 创建会话列表项
                sessions.forEach(session => {
                    const sessionItem = document.createElement('div');
                    sessionItem.className = 'session-item';
                    sessionItem.style = 'padding: 12px 16px; margin-bottom: 4px; border-radius: 12px; cursor: pointer; transition: background-color 0.2s;';
                    sessionItem.dataset.sessionId = session.sessionId;
                    sessionItem.dataset.dbId = session.id;

                    // 如果是当前会话，高亮显示
                    if (currentSession && currentSession.sessionId === session.sessionId) {
                        sessionItem.style.backgroundColor = '#e0dfee';
                    }

                    sessionItem.innerHTML = `
                    <div style="font-weight: 500; margin-bottom: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">${session.title}</div>
                    <div style="font-size: 12px; color: #999; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">${formatDateTime(session.updateTime)}</div>
                `;

                    // 添加点击事件
                    sessionItem.addEventListener('click', () => {
                        loadSessionChat(session);
                    });

                    // 添加右键菜单（删除会话）
                    sessionItem.addEventListener('contextmenu', (e) => {
                        e.preventDefault();
                        if (confirm(`确定要删除会话"${session.title}"吗？`)) {
                            deleteSession(session.id);
                        }
                    });

                    sessionListElement.appendChild(sessionItem);
                });
            })
            .catch(error => {
                console.error('加载会话列表失败:', error);
                sessionListElement.innerHTML = '<div style="text-align: center; padding: 20px; color: #ff4d4f;">加载失败，请重试</div>';
            });
    }

    // 格式化日期时间
    function formatDateTime(dateTimeString) {
        const date = new Date(dateTimeString);
        const now = new Date();
        const diff = now - date;
        const minutes = Math.floor(diff / (1000 * 60));
        const hours = Math.floor(diff / (1000 * 60 * 60));
        const days = Math.floor(diff / (1000 * 60 * 60 * 24));

        if (minutes < 1) return '刚刚';
        if (minutes < 60) return `${minutes}分钟前`;
        if (hours < 24) return `${hours}小时前`;
        if (days < 7) return `${days}天前`;

        return `${date.getMonth() + 1}月${date.getDate()}日`;
    }

    // 创建新会话
    function createNewSession() {
        const initialMessage = '你好';

        // 修复：将参数名从character改为role，与后端接口保持一致
        axios.post('http://localhost:8080/user/ai-session/create', null, {
            params: {
                userId: userId,
                role: 'harry_potter', // 这里将character改为role
                initialMessage: initialMessage
            }
        })
            .then(response => {
                const newSession = response.data.data;
                // 清除当前聊天内容
                clearChat();
                // 设置新会话
                currentSession = newSession;
                // 重新加载会话列表
                loadSessionList();
                // 设置sessionId
                sessionId = newSession.sessionId;

                // 自动发送第一条消息
                const userBubble = document.createElement('div');
                userBubble.className = 'chat-message user';
                userBubble.textContent = initialMessage;
                chatBubbleList.appendChild(userBubble);
                chatBubbleList.scrollTop = chatBubbleList.scrollHeight;

                // 发送消息到AI
                initWebSocket();
                // 等待WebSocket连接建立
                setTimeout(() => {
                    if (ws && ws.readyState === WebSocket.OPEN) {
                        ws.send(JSON.stringify({
                            type: 'text_message',
                            text: initialMessage,
                            userId: userId,
                            sessionId: sessionId,
                            character: 'harry_potter'
                        }));
                    }
                }, 500);
            })
            .catch(error => {
                console.error('创建会话失败:', error);
                showStatus(chatStatus, '错误', '创建会话失败', 'error');
            });
    }

    // 加载会话聊天记录
    function loadSessionChat(session) {
        // 清除当前聊天内容
        clearChat();

        // 设置当前会话
        currentSession = session;
        sessionId = session.sessionId;

        // 更新会话列表高亮
        const sessionItems = document.querySelectorAll('.session-item');
        sessionItems.forEach(item => {
            if (item.dataset.sessionId === session.sessionId) {
                item.style.backgroundColor = '#e0dfee';
            } else {
                item.style.backgroundColor = 'transparent';
            }
        });

        // 加载历史消息
        // 修复：使用完整的URL并确保参数名为sessionId且值为session.id（数据库ID）
        axios.get('http://localhost:8080/user/ai-session/messages', {
            params: {sessionId: session.id}
        })
            .then(response => {
                const messages = response.data.data;

                messages.forEach(message => {
                    const messageElement = document.createElement('div');
                    messageElement.className = message.role === 0 ? 'chat-message user' : 'chat-message ai';
                    messageElement.textContent = message.content;
                    chatBubbleList.appendChild(messageElement);
                });

                chatBubbleList.scrollTop = chatBubbleList.scrollHeight;
            })
            .catch(error => {
                console.error('加载聊天记录失败:', error);
            });
    }

    // 删除会话
    function deleteSession(sessionDbId) {
        // 修复：使用完整的URL
        axios.delete(`http://localhost:8080/user/ai-session/${sessionDbId}`)
            .then(() => {
                // 如果删除的是当前会话，清除聊天内容
                if (currentSession && currentSession.id === sessionDbId) {
                    clearChat();
                    currentSession = null;
                    sessionId = 'session_' + Date.now(); // 生成新的会话ID
                }
                // 重新加载会话列表
                loadSessionList();
            })
            .catch(error => {
                console.error('删除会话失败:', error);
                alert('删除会话失败，请重试');
            });
    }

    // 清除聊天内容
    function clearChat() {
        const chatBubbleList = document.getElementById('chatBubbleList');
        chatBubbleList.innerHTML = '';
    }

    // 语音通话按钮功能
    function startVoiceChat() {
        toggleChatMode();
        // 可以根据需要添加更多逻辑
    }
</script>
</body>
</html>